package cn.tedu.user.management.service.impl;

import cn.tedu.rtms.commons.ex.ServiceException;
import cn.tedu.rtms.commons.pojo.vo.PageData;
import cn.tedu.rtms.commons.web.ServiceCode;
import cn.tedu.user.management.dao.persist.repository.ISectionJobRepository;
import cn.tedu.user.management.dao.persist.repository.ISectionRepository;
import cn.tedu.user.management.dao.persist.repository.IUserRepository;
import cn.tedu.user.management.pojo.entity.Section;
import cn.tedu.user.management.pojo.param.SectionAddNewParam;
import cn.tedu.user.management.pojo.param.SectionUpdateInfoParam;
import cn.tedu.user.management.pojo.vo.SectionListItemVO;
import cn.tedu.user.management.pojo.vo.SectionStandardVO;
import cn.tedu.user.management.pojo.vo.SectionTreeItemVO;
import cn.tedu.user.management.service.ISectionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 处理部门数据的业务实现类
 *
 * @author java@tedu.cn
 * @version 0.0.1
 */
@Slf4j
@Service
public class SectionServiceImpl implements ISectionService {

    @Value("${csmall.crud.default-query-page-size}")
    private Integer defaultQueryPageSize;
    @Value("${csmall.jwt.secret-key}")
    private String secretKey;
    @Value("${csmall.jwt.duration-in-minute}")
    private Long durationInMinute;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private ISectionRepository sectionRepository;
    @Autowired
    private ISectionJobRepository sectionJobRepository;
    @Autowired
    private IUserRepository userRepository;
    /*@Autowired
    private ISectionRoleRepository sectionRoleRepository;*/
    /*@Autowired
    private ISectionJwtRepository sectionCacheRepository;*/
    @Autowired
    private AuthenticationManager authenticationManager;

    public SectionServiceImpl() {
        log.debug("创建业务类对象：SectionServiceImpl");
    }

    @Override
    public void addNew(SectionAddNewParam sectionAddNewParam) {
        log.debug("开始处理【新增部门】的业务，参数：{}", sectionAddNewParam);

        // 检查部门名是否被占用
        // 从参数对象中获取部门的部门名
        String sectionName = sectionAddNewParam.getSectionName();
        // 调用Mapper对象的countBySectionName()执行统计
        int count = sectionRepository.countBySectionName(sectionName);
        // 判断统计结果是否大于0
        if (count > 0) {
            // 是：抛出异常
            String message = "添加部门失败，部门名已经被占用！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_CONFLICT, message);
        }

        //判断负责人是否存在
        Long headId = sectionAddNewParam.getUserId();
        count = userRepository.countById(headId);
        // 判断统计结果
        if (count != 1) {
            // 是：抛出异常
            String message = "添加部门失败，负责人不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_CONFLICT, message);
        }

        // 创建Section对象
        Section section = new Section();
        // 复制属性
        BeanUtils.copyProperties(sectionAddNewParam, section);

        section.setHeadId(headId);
        // 调用Mapper对象的insert()执行插入
        int rows = sectionRepository.insert(section);
        if (rows != 1) {
            String message = "添加部门失败，服务器忙，请稍后再尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_INSERT, message);
        }

        //若有父级部门，则需要将父级部门的is_parent设置为1
        Long parentId = sectionAddNewParam.getParentId();
        if (parentId != 0) {
            log.debug("开始处理【修改父级is_parent的业务】的业务，参数：{}", parentId);
            // 创建Section对象
            Section parentSection = new Section();
            parentSection.setId(parentId);
            parentSection.setIsParent(1);
            rows = sectionRepository.update(parentSection);
            if (rows != 1) {
                String message = "修改父级部门is_parent参数失败，服务器忙，请稍后再尝试！";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERROR_INSERT, message);
            }
        }

    }

    @Override
    public void delete(Long id) {
        log.debug("开始处理【根据id删除部门】的业务，参数：{}", id);
        // 检查尝试删除的数据是否存在
        Object queryResult = sectionRepository.getStandardById(id);
        if (queryResult == null) {
            String message = "删除部门失败，尝试访问的数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
        }

        //检查该部门是否有职位存在
        log.debug("检查该部门是否有职位存在，参数：{}", id);
        int count = sectionJobRepository.countBySectionId(id);
        if (count > 0) {
            String message = "删除部门失败，该部门还有职位存在，无法删除！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_DELETE, message);
        }

        //判断该部门是否是父级部门
        log.debug("判断该部门是否是父级部门，参数：{}", id);
        Integer isParent = sectionRepository.selectIsParentById(id);
        if (isParent == 1) {
            String message = "删除部门失败，该部门还有子级部门存在，无法删除！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_DELETE, message);
        }

        //判断该部门是否存在父级部门，即parentId是否等于0
        log.debug("判断该部门是否存在父级部门，参数：{}", id);
        Long parentId = sectionRepository.selectParentIdById(id);
        if (parentId == 0) {
            //无父级部门，直接删除
            deleteById(id);
        } else {
            //有父级部门，查询该父级部门的子级部门数量
            count = sectionRepository.childrenSectionCountByParentId(parentId);

            if (count == 1) {
                //为1，则删除后需将父级部门的isParent改为0
                deleteById(id);
                //修改父级部门的isParent为0
                int rows = sectionRepository.updateParentSectionIsParent(parentId);
                if (rows != 1) {
                    String message = "修改父级部门的is_parent失败，服务器忙，请稍后再尝试！";
                    log.warn(message);
                    throw new ServiceException(ServiceCode.ERROR_DELETE, message);
                }
            } else {
                //直接删除
                deleteById(id);
            }
        }

    }

    private void deleteById(Long id) {
        // 执行删除--部门表
        log.debug("即将执行删除数据，参数：{}", id);
        int rows = sectionRepository.deleteById(id);
        if (rows != 1) {
            String message = "删除部门失败，服务器忙，请稍后再尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_DELETE, message);
        }
    }

    @Override
    public PageData<SectionListItemVO> list(Integer pageNum) {
        log.debug("开始处理【查询部门列表】的业务，页码：{}", pageNum);
        PageData<SectionListItemVO> pageData = sectionRepository.list(pageNum, defaultQueryPageSize);
        return pageData;
    }

    @Override
    public PageData<SectionListItemVO> list(Integer pageNum, Integer pageSize) {
        log.debug("开始处理【查询部门列表】的业务，页码：{}，每页记录数：{}", pageNum, pageSize);
        PageData<SectionListItemVO> pageData = sectionRepository.list(pageNum, pageSize);
        return pageData;
    }

    @Override
    public List<SectionListItemVO> list() {
        log.debug("开始处理【查询部门名称列表(不分页)】的业务");
        List<SectionListItemVO> list = sectionRepository.list();
        return list;
    }

    @Override
    public List<SectionListItemVO> list(Long parentId) {
        log.debug("开始处理【查询子级部门名称列表(不分页)】的业务");
        List<SectionListItemVO> list = sectionRepository.list(parentId);
        return list;
    }

    @Override
    public void updateInfoById(Long id, SectionUpdateInfoParam sectionUpdateInfoParam) {
        log.debug("开始处理【修改部门信息】的业务，ID：{}，新数据：{}", id, sectionUpdateInfoParam);
        // 调用Mapper对象的getStandardById()执行查询
        SectionStandardVO queryResult = sectionRepository.getStandardById(id);
        // 判断查询结果是否为null
        if (queryResult == null) {
            // 是：抛出异常
            String message = "修改部门信息失败，尝试修改的部门数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
        }

        // 调用Mapper对象的countByNameAndNotId()执行统计
        int count = sectionRepository.countBySectionNameAndNotId(id, sectionUpdateInfoParam.getSectionName());
        // 判断统计结果是否大于0
        if (count > 0) {
            // 是：名称被占用，抛出异常
            String message = "修改部门信息失败，该部门名已经被占用！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_CONFLICT, message);
        }

        //判断是否未null,防止空指针
        if(sectionUpdateInfoParam.getUserId()==null){
            // 创建Section对象
            Section section = new Section();
            // 复制属性，设置ID
            BeanUtils.copyProperties(sectionUpdateInfoParam, section);
            section.setId(id);
            // 调用Mapper对象的update()方法执行修改
            int rows = sectionRepository.update(section);
            if (rows != 1) {
                String message = "修改部门信息失败，服务器忙，请稍后再尝试！";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERROR_UPDATE, message);
            }
            return ;
        }

        //获取部门负责人
        count= userRepository.countById(sectionUpdateInfoParam.getUserId());
        if (count < 1) {
            String message = "您输入的部门负责人不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_CONFLICT, message);
        }
        if (count == 1) {
            // 创建Section对象
            Section section = new Section();
            // 复制属性，设置ID
            BeanUtils.copyProperties(sectionUpdateInfoParam, section);
            section.setId(id);
            section.setHeadId(sectionUpdateInfoParam.getUserId());
            // 调用Mapper对象的update()方法执行修改
            int rows = sectionRepository.update(section);
            if (rows != 1) {
                String message = "修改部门信息失败，服务器忙，请稍后再尝试！";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERROR_UPDATE, message);
            }

        }

    }

    @Override
    public SectionStandardVO getStandardById(Long id) {
        log.debug("开始处理【根据ID查询部门信息】的业务，参数：{}", id);
        SectionStandardVO queryResult = sectionRepository.getStandardById(id);
        if (queryResult == null) {
            // 是：抛出异常
            String message = "查询部门信息失败，部门数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
        }
        return queryResult;
    }

    @Override
    public List<SectionTreeItemVO> listTree() {
        log.debug("开始处理【获取部门树】的业务，参数：无");
        return commonsListTree(sectionRepository.list());
    }

    @Override
    public List<SectionTreeItemVO> listEnableTree() {
        log.debug("开始处理【获取招聘部门树】的业务，参数：无");
        return commonsListTree(sectionRepository.enableList());
    }

    private List<SectionTreeItemVO> commonsListTree(List<SectionListItemVO> sectionList) {
        log.debug("【获取部门树公用部分】");
        List<SectionTreeItemVO> sectionTree = new ArrayList<>();
        Map<Long, SectionListItemVO> allSectionMap = transformListToMap(sectionList);
        for (Long key : allSectionMap.keySet()) {
            SectionListItemVO mapItem = allSectionMap.get(key);
            if (mapItem.getParentId() == 0) {
                SectionTreeItemVO sectionTreeItemVO = convertListItemToTreeItem(mapItem);
                sectionTree.add(sectionTreeItemVO);

                fillChildren(mapItem, sectionTreeItemVO, allSectionMap);
            }
        }

        return sectionTree;
    }

    private Map<Long, SectionListItemVO> transformListToMap(List<SectionListItemVO> sectionList) {
        Map<Long, SectionListItemVO> sectionMap = new LinkedHashMap<>();
        for (SectionListItemVO sectionListItemVO : sectionList) {
            sectionMap.put(sectionListItemVO.getId(), sectionListItemVO);
        }
        return sectionMap;
    }

    private void fillChildren(SectionListItemVO listItem, SectionTreeItemVO currentTreeItem, Map<Long, SectionListItemVO> allSectionMap) {
        if (listItem.getIsParent() == 1) {
            currentTreeItem.setChildren(new ArrayList<>());
            Set<Long> keySet = allSectionMap.keySet();
            for (Long key : keySet) {
                SectionListItemVO mapItem = allSectionMap.get(key);
                if (mapItem.getParentId() == listItem.getId()) {
                    SectionTreeItemVO sectionTreeSubItemVO = convertListItemToTreeItem(mapItem);
                    currentTreeItem.getChildren().add(sectionTreeSubItemVO);
                    if (mapItem.getIsParent() == 1) {
                        fillChildren(mapItem, sectionTreeSubItemVO, allSectionMap);
                    }
                }
            }
        }
    }

    private SectionTreeItemVO convertListItemToTreeItem(SectionListItemVO listItem) {
        return new SectionTreeItemVO()
                .setValue(listItem.getId())
                .setLabel(listItem.getSectionName());
    }

}
